function getWifiInfo(callback) {
	wx.startWifi({
		success(res) {
			// console.log('startWifi', res)
			wx.getConnectedWifi({
				success(res1) {
					// console.log(res1.wifi)
					callback({"code":1,"result":"success","ssid":res1.wifi.SSID, "is5G":res1.wifi.frequency>4900})
				},
				fail(error) {
					console.log(error);
					callback({"code":2, "result":JSON.stringify(error)})
				}
			})
		},
		fail(error) {
			console.log(error);
			callback({"code":2, "result":JSON.stringify(error)})
		}
	})
}
var wxUdp = null;
var closeFlag = false;
var successFlag = false;
var ip;

function startConfig(ssid, password, localIp, callback) {
	// console.log(ssid, password, localIp);
	if(wxUdp != null) {
		return;
	}
	ip = localIp;
	AirkissEncoder(ssid, password);
	// console.log(mRandomChar);
	// console.log(mEncodedData.length);
	wxUdp = wx.createUDPSocket();
	if (wxUdp == null) {
		wx.showToast({
			title: '不支持udp通信！',
		})
		return;
	}
	let port = wxUdp.bind(10000);
	// console.log("监听端口：" + port);
	closeFlag = false;
	successFlag = false;
	// wxUdp.onListening(function(res) {
	// 	console.log('监听中Res ===', res)
	// })
	var replyByteCounter = 0;
	wxUdp.onMessage(function(res) {
		if (res.remoteInfo.size > 0) {
			let unit8Arr = new Uint8Array(res.message);
			// var msg = [];
			let arrLength = unit8Arr.length;
			for(let i=0; i<arrLength; i++) {
				if(unit8Arr[i] == mRandomChar) {
					// console.log("匹配成功:", JSON.stringify(unit8Arr));
					replyByteCounter++;
					break;
				}
			}
			if(replyByteCounter >= 3) {
				// console.log("配网成功:", JSON.stringify(unit8Arr));
				successFlag = true;
				var bssid = '';
				for(let i=1; i<unit8Arr.length; i++) {
					let d = unit8Arr[i].toString(16);
					bssid += (d.length==1?'0'+d : d);
				}
				callback({"ip":res.remoteInfo.address,"bssid":bssid,"result": "success", "code":1});
				//关闭udp
				wxUdp.offMessage();
				wxUdp.close();
				wxUdp = null;
				mEncodedData = null;
			}
		}
	});
	wxUdp.onError(function(e) {
		console.log(e);
	})
	socketSend(0);
	countDown(new Date().getTime(), callback);
}
function countDown(start, callback) {
	if(closeFlag || successFlag) {
		if(closeFlag) {
			callback({"code":4, "result":"用户取消"});
		}
		return;
	}
	let now = new Date().getTime();
	if((now - start) > 55000) {
		callback({"code":3, "result":"配网超时"});
		cancel();
		return;
	}
	setTimeout(()=>{
		countDown(start, callback);
	},1000)
}
function socketSend(index) {
	if(closeFlag || successFlag) {
		// console.log(successFlag?'配网成功...':'发送关闭...');
		mEncodedData = null;
		return;
	}
	if(index == mEncodedData.length) {
		// console.log('发送完毕...');
		socketSend(0);//继续发送，直到超时
		return;
	}
	let sendData = new ArrayBuffer(mEncodedData[index]);
	wxUdp.send({
		address: ip,
		port: 10000,
		message: sendData,
		setBroadcast:true
	});
	setTimeout(()=>{
		socketSend(++index);
	},5)
}
function cancel() {
	closeFlag = true;
	if (wxUdp != null) {
		wxUdp.offMessage();
		wxUdp.close();
		wxUdp = null;
		mEncodedData = null;
		// console.log("udp is closed");
	}
}
var mEncodedData = null; //32768
var mRandomChar = 0;

function leadingPart() {
	for (let i = 0; i < 50; ++i) {
		for (let j = 1; j <= 4; ++j) {
			appendEncodedData(j);
		}
	}
}

function appendEncodedData(data) {
	mEncodedData.push(data);
}

function magicCode(ssid, password) {
	let bytes = strToUtf8Bytes(ssid);
	let length = bytes.length + password.length + 1;
	let magicCode = [];
	magicCode[0] = 0x00 | (length >>> 4 & 0xF);
	if (magicCode[0] == 0) {
		magicCode[0] = 0x08;
	}
	magicCode[1] = 0x10 | (length & 0xF);
	let crc8 = CRC8(bytes);
	magicCode[2] = 0x20 | (crc8 >>> 4 & 0xF);
	magicCode[3] = 0x30 | (crc8 & 0xF);
	for (let i = 0; i < 20; ++i) {
		for (let j = 0; j < 4; ++j) {
			appendEncodedData(magicCode[j]);
		}
	}
}

function CRC8(bytes) {
	let len = bytes.length;
	let i = 0;
	let crc = 0x00;
	while (len-- > 0) {
		let extract = bytes[i++];
		for (let tempI = 8; tempI != 0; tempI--) {
			let sum = ((crc & 0xFF) ^ (extract & 0xFF));
			sum = ((sum & 0xFF) & 0x01);
			crc = ((crc & 0xFF) >>> 1);
			if (sum != 0) {
				crc = ((crc & 0xFF) ^ 0x8C);
			}
			extract = ((extract & 0xFF) >>> 1);
		}
	}
	return (crc & 0xFF);
}

function prefixCode(password) {
	let length = password.length;
	let prefixCode = [];
	prefixCode[0] = 0x40 | (length >>> 4 & 0xF);
	prefixCode[1] = 0x50 | (length & 0xF);
	let crc8 = CRC8([length]);
	prefixCode[2] = 0x60 | (crc8 >>> 4 & 0xF);
	prefixCode[3] = 0x70 | (crc8 & 0xF);
	// console.log(prefixCode.join());
	for (let j = 0; j < 4; ++j) {
		appendEncodedData(prefixCode[j]);
	}
}

function sequence(index, data) {
	// console.log(index, data);
	let content = []; //new byte[data.length + 1];
	content[0] = (index & 0xFF);
	content = content.concat(data);
	let crc8 = CRC8(content);
	appendEncodedData(0x80 | crc8);
	appendEncodedData(0x80 | index);
	data.forEach((aData, index) => {
		let bData = (aData & 0xff);
		let result = bData | 0x100;
		appendEncodedData(result);
	});
}

function AirkissEncoder(ssid, password) {
	mEncodedData = []; //32768
	mRandomChar = Math.floor(Math.random() * 127);
	let times = 5;
	let d1 = strToUtf8Bytes(password);
	let d2 = strToUtf8Bytes(ssid);
	let datas = [];
	datas = datas.concat(d1);
	datas.push(mRandomChar);
	datas = datas.concat(d2);
	// console.log(datas.join());
	var llength = parseInt(datas.length / 4);
	while (times-- > 0) {
		leadingPart();
		magicCode(ssid, password);
		for (let i = 0; i < 15; ++i) {
			prefixCode(password);

			for (let idx = 0; idx < llength; idx++) {
				let content = [];
				for (let start = idx * 4; start < (idx + 1) * 4; start++) {
					content.push(datas[start]);
				}
				// console.log(idx + "#" + content.join(", "));
				sequence(idx, content);
				// index = idx;
			}
			if (datas.length % 4 != 0) {
				let content = [];
				let mod = datas.length % 4;
				let ss = llength * 4;
				for (let start1 = ss; start1 < ss + mod; start1++) {
					content.push(datas[start1]);
				}
				sequence(llength, content);
			}
		}
	}
	return mEncodedData;
}

function strToUtf8Bytes(str) {
	const utf8 = [];
	for (let ii = 0; ii < str.length; ii++) {
		let charCode = str.charCodeAt(ii);
		if (charCode < 0x80) utf8.push(charCode);
		else if (charCode < 0x800) {
			utf8.push(0xc0 | (charCode >> 6), 0x80 | (charCode & 0x3f));
		} else if (charCode < 0xd800 || charCode >= 0xe000) {
			utf8.push(0xe0 | (charCode >> 12), 0x80 | ((charCode >> 6) & 0x3f), 0x80 | (charCode & 0x3f));
		} else {
			ii++;
			charCode = 0x10000 + (((charCode & 0x3ff) << 10) | (str.charCodeAt(ii) & 0x3ff));
			utf8.push(
				0xf0 | (charCode >> 18),
				0x80 | ((charCode >> 12) & 0x3f),
				0x80 | ((charCode >> 6) & 0x3f),
				0x80 | (charCode & 0x3f),
			);
		}
	}
	//兼容汉字，ASCII码表最大的值为127，大于127的值为特殊字符
	for (let jj = 0; jj < utf8.length; jj++) {
		var code = utf8[jj];
		if (code > 127) {
			utf8[jj] = code - 256;
		}
	}
	return utf8;
}
//0:不支持配网，需要升级；1：需要获取IP地址；2：支持
function checkSystem() {
	var rtn = 2;
	try {
		const res = wx.getSystemInfoSync();
		if(compareVersion(res.SDKVersion,'2.9.0')<0) {//基础库版本低于这个无法使用udp广播
			rtn = 0;
		}
		// console.log(res);
		if (rtn ==2 && res.platform == 'ios') {
			let osVersion = parseFloat(res.system.substr(4));
			if(osVersion >= 14.5 && osVersion < 15) {
				if(compareVersion(res.SDKVersion,'2.24.0')<0) {
					rtn = 0;
				} else {
					rtn = 1;
				}
			}
		}
		if(rtn == 0) {
			wx.showModal({
				title: '提示',
				showCancel: false,
				content: '当前微信版本不支持配网，请升级微信版本后重试！'
			})
		}
	} catch (e) {
		// console.log(e);
	}
	return rtn;
}
function compareVersion(v1, v2) {
  v1 = v1.split('.')
  v2 = v2.split('.')
  const len = Math.max(v1.length, v2.length)

  while (v1.length < len) {
    v1.push('0')
  }
  while (v2.length < len) {
    v2.push('0')
  }

  for (let i = 0; i < len; i++) {
    const num1 = parseInt(v1[i])
    const num2 = parseInt(v2[i])

    if (num1 > num2) {
      return 1
    } else if (num1 < num2) {
      return -1
    }
  }

  return 0
}

module.exports = {
	getWifiInfo: getWifiInfo,
	startConfig: startConfig,
	cancel: cancel,
	checkSystem:checkSystem
}
